const Router = require('koa-router');
const router = Router();

const { env } = require('../index');

const docs = {
  openapi: '3.0.1',
  info: {
    title: env.title || 'Swagger',
    description: env.apiDescription || 'Swagger WebApi description',
    version: 'v1',
    serviceName: 'monitor'
  },
  paths: null,
  components: {
    schemas: {
      dynamicObject: {
        type: 'object'
      },
      filters: {
        type: 'array',
        items: {
          $ref: '#/components/schemas/filterItem'
        }
      },
      filterItem: {
        type: 'object',
        properties: {
          field: {
            type: 'string',
            nullable: false,
            description: '表(虚表)字段'
          },
          op: {
            type: 'string',
            nullable: true,
            description: '操作字符(=、>、>=、<、<=、like、starts、ends)'
          },
          join: {
            type: 'string',
            nullable: true,
            description: '连接方式(and、or)'
          },
          value: {
            type: 'object',
            nullable: true,
            description: '值'
          }
        },
        example: {
          field: '',
          op: '=',
          value: ''
        }
      }
    },
    securitySchemes: {
      Bearer: {
        type: 'http',
        description: '请输入JWT Bearer access token的值',
        scheme: 'Bearer',
        bearerFormat: 'JWT'
      }
    }
  },
  security: [{ Bearer: [] }]
};

router.all('/api/health', async (ctx, next) => {
  await (ctx.body = 'OK');
}, '健康检查');

router.get('/swagger/v1/swagger.json', (ctx, next) => {
  if (!docs.paths) {
    let path = {};
    for (let item of global.routes) {
      if (!item.path.startsWith('/api')) {
        continue;
      }

      let apiPath = item.path;
      let tag = item.opts.prefix || item.path;
      let method = 'get';

      if (item.methods.includes('POST')) {
        method = 'post';
      } else if (item.methods.includes('DELETE')) {
        method = 'delete';
      } else if (item.methods.includes('PUT')) {
        method = 'put';
      }

      let detail = {};
      let summary = { desc: '' };

      if (Router.documents && Router.documents instanceof Map) {
        tag = Router.documents.get(tag) || tag;
        summary = Router.documents.get(`${method} - ${item.path}`) || { desc: '' };
      }

      detail[method] = {
        tags: [tag],
        summary: summary.desc,
        produces: ['application/json'],
        responses: {
          "200": {
            description: "成功！"
          },
          "401": {
            description: '认证失败！'
          },
          "500": {
            description: '执行服务发生错误！'
          }
        }
      };

      if (item.paramNames && item.paramNames.length > 0) {
        let parameters = [];

        for (let parm of item.paramNames) {
          apiPath = apiPath.replace(new RegExp(`:${parm.name}`, 'ig'), `{${parm.name}}`);

          parameters.push({
            name: parm.name,
            in: 'path',
            required: true,
            description: summary[parm.name]
          });
        }

        detail[method].parameters = parameters;
      }

      if (method == 'post' || method == 'put') {
        let requestBody = {
          content: {

          }
        };

        if (summary.multipart && Array.isArray(summary.multipart) && summary.multipart.length > 0) {
          let properties = {};

          summary.multipart.forEach(r => {
            properties[r.name] = {
              type: r.type,
              description: r.desc
            }
          });

          requestBody.content['multipart/form-data'] = {
            schema: {
              type: 'object',
              properties: properties,
              description: summary.desc
            }
          };
        } else if (summary.body && typeof summary.body == 'object') {
          let schemaName = apiPath.replace(/[{}\/]/ig, '');

          let properties = {};
          let bodyProps = Object.getOwnPropertyNames(summary.body);

          for (let prop of bodyProps) {
            let item = summary.body[prop];

            if (item.$ref) {
              properties[prop] = {
                $ref: `#/components/schemas/${item.$ref}`
              };
            } else {
              properties[prop] = {
                type: item.type || 'string',
                description: item.desc || ''
              };

              if (item.items) {
                properties[prop].items = item.items;
              }
            }
          }

          docs.components.schemas[schemaName] = {
            type: 'object',
            properties: properties,
            description: summary.desc
          };

          requestBody.content['application/json'] = {
            schema: {
              '$ref': `#/components/schemas/${schemaName}`
            }
          };
        } else {
          requestBody.content["application/json"] = {
            schema: {
              $ref: '#/components/schemas/dynamicObject'
            }
          };
        }

        detail[method].requestBody = requestBody;
      }

      if (path[apiPath]) {
        path[apiPath][method] = detail[method];
      } else {
        path[apiPath] = detail;
      }
    }

    docs.paths = path;
  }

  ctx.body = docs;
});

module.exports = router;